<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .box {
      margin: 20px;
      background-color: red;
    }

    ul {
      position: relative;
      padding: 50px;
      list-style: none;
    }

    li {
      position: absolute;
      border: 1px solid red;
      width: 100px;
      height: 100px;
      background: gray;
    }
  </style>
  <script>
    const liArr = document.querySelectorAll('li');
    liArr.forEach(li => {
      li.style.height = Math.random() * 400 + 100 + 'px';
    })

    const gap = 10;
    const itemWidth = liArr[0].offsetWidth;
    
    // 计算列数
    const row = parseInt(document.body.clientWidth / (liArr[0].offsetWidth + gap));

    const topArr = [];

    liArr.forEach((li, idx) => {
      if (idx < row) {
        li.style.top = 0;
        li.style.left = (itemWidth + gap) * idx + 'px';
        // 初始填充
        topArr.push(li.offsetHeight);
      } else {
        let index = 0,
          minHeight = topArr[0];
        // 遍历找出最小高度项
        topArr.forEach((item, idx) => {
          if (minHeight > item) {
            minHeight = item;
            index = idx;
          }
        })

        li.style.top = minHeight + gap + 'px';
        li.style.left = index * (itemWidth + gap) + 'px';

        // 将最小高度项替换为自身
        topArr[index] = minHeight + li.offsetHeight + gap;
      }
    })



  </script>
</body>

</html>